package com.canaan.business.service.invoice.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.canaan.business.common.enums.inOutStock.OutOrderStatusEnum;
import com.canaan.business.common.enums.inOutStock.OutStockOrderTypeEnum;
import com.canaan.business.domain.basic.WmsProduct;
import com.canaan.business.domain.inOutStock.WmsOutStockOrder;
import com.canaan.business.domain.invoice.WmsSalesOrder;
import com.canaan.business.domain.invoice.WmsSalesOrderDetail;
import com.canaan.business.domain.vo.StockDetailProductVo;
import com.canaan.business.domain.vo.WmsSalesOrderVo;
import com.canaan.business.mapper.invoice.WmsSalesOrderMapper;
import com.canaan.business.service.basic.IWmsBaseCustomerService;
import com.canaan.business.service.basic.IWmsProductService;
import com.canaan.business.service.inOutStock.IWmsOutStockOrderService;
import com.canaan.business.service.invoice.IWmsSalesOrderDetailService;
import com.canaan.business.service.invoice.IWmsSalesOrderService;
import com.canaan.common.constant.PrefixConstants;
import com.canaan.common.exception.ServiceException;
import com.canaan.common.utils.DateUtils;
import com.canaan.common.utils.SecurityUtils;
import com.canaan.common.utils.StringUtils;
import com.canaan.common.utils.TableNoUtil;
import org.apache.commons.compress.utils.Lists;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 销售订单Service业务层处理
 *
 * @author ruoyi
 * @date 2022-12-13
 */
@Service
public class WmsSalesOrderServiceImpl implements IWmsSalesOrderService
{
    @Resource
    private WmsSalesOrderMapper wmsSalesOrderMapper;

    @Resource
    private IWmsSalesOrderDetailService wmsSalesOrderDetailService;

    @Resource
    private IWmsProductService wmsProductService;

    @Resource
    private IWmsBaseCustomerService wmsBaseCustomerService;

    @Resource
    private IWmsOutStockOrderService wmsOutStockOrderService;

    /**
     * 查询销售订单
     *
     * @param id 销售订单主键
     * @return 销售订单
     */
    @Override
    public WmsSalesOrder selectWmsSalesOrderById(Long id)
    {
        return wmsSalesOrderMapper.selectWmsSalesOrderById(id);
    }

    /**
     * 查询销售单据
     *
     * @param no 编号
     * @return 销售单据
     */
    @Override
    public WmsSalesOrder selectWmsSalesOrderByNo(String no) {
        return wmsSalesOrderMapper.selectWmsSalesOrderByNo(no);
    }

    /**
     * 查询销售订单列表
     *
     * @param wmsSalesOrder 销售订单
     * @return 销售订单
     */
    @Override
    public List<WmsSalesOrder> selectWmsSalesOrderList(WmsSalesOrder wmsSalesOrder)
    {
        return wmsSalesOrderMapper.selectWmsSalesOrderList(wmsSalesOrder);
    }

    /**
     * 新增销售订单
     *
     * @param wmsSalesOrder 销售订单
     * @return 结果
     */
    @Override
    public int insertWmsSalesOrder(WmsSalesOrder wmsSalesOrder)
    {
        if(StringUtils.isEmpty(wmsSalesOrder.getNo())){
            wmsSalesOrder.setNo(PrefixConstants.SALES_SLIP+TableNoUtil.getNo(WmsSalesOrder.class));
        }
        wmsSalesOrder.setOrderStatus(OutOrderStatusEnum.NEW.getCode());
        wmsSalesOrder.setCreateBy(SecurityUtils.getUsername());
        wmsSalesOrder.setCreateTime(DateUtils.getNowDate());
        return wmsSalesOrderMapper.insertWmsSalesOrder(wmsSalesOrder);
    }

    /**
     * 修改销售订单
     *
     * @param wmsSalesOrder 销售订单
     * @return 结果
     */
    @Override
    public int updateWmsSalesOrder(WmsSalesOrder wmsSalesOrder)
    {
        wmsSalesOrder.setUpdateBy(SecurityUtils.getUsername());
        wmsSalesOrder.setUpdateTime(DateUtils.getNowDate());
        return wmsSalesOrderMapper.updateWmsSalesOrder(wmsSalesOrder);
    }

    /**
     * 发货
     *
     * @param ids 发货的主键id
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int shipments(List<Long> ids)
    {
        WmsSalesOrder order = new WmsSalesOrder();
        order.setIds(ids);
        List<WmsSalesOrder> orders = this.selectWmsSalesOrderList(order);
        orders = orders.stream().filter(e -> !OutOrderStatusEnum.ACCOMPLISH.getCode().equals(e.getOrderStatus())).collect(Collectors.toList());
        if(orders.isEmpty()){
            return 0;
        }
        List<WmsOutStockOrder> wmsOutStockOrderList = Lists.newArrayList();
        for (WmsSalesOrder wmsSalesOrder : orders){
            WmsOutStockOrder wmsOutStockOrder = this.wmsOutStockOrderService.selectWmsOutStockOrderByRelOrderNo(wmsSalesOrder.getNo(),1);
            wmsOutStockOrderList.add(wmsOutStockOrder);
        }

        Map<String,List<WmsOutStockOrder>> detailMap = wmsOutStockOrderList.stream().collect(Collectors.groupingBy(WmsOutStockOrder::getRelOrderNo));
        List<String> errorNos = new ArrayList<>();
        for (WmsSalesOrder salesOrder : orders) {
            boolean isAlreadyPicking = detailMap.getOrDefault(salesOrder.getNo(),Collections.emptyList()).stream()
                    .allMatch(e -> OutOrderStatusEnum.ACCOMPLISH.getCode().equals(e.getOrderStatus()));
            if (!isAlreadyPicking) {
                errorNos.add(salesOrder.getNo());
            }
        }
        if(!errorNos.isEmpty()){
            throw new ServiceException("销售订单" + errorNos +"下还有未拣货完成的销售出库单");
        }
        String username = SecurityUtils.getUsername();
        Date date = DateUtils.getNowDate();
        for (WmsSalesOrder wmsSalesOrder : orders) {
            wmsSalesOrder.setOrderStatus(OutOrderStatusEnum.ACCOMPLISH.getCode());
            wmsSalesOrder.setUpdateBy(username);
            wmsSalesOrder.setUpdateTime(date);
            wmsSalesOrder.setCompleteTime(date);
            wmsSalesOrderMapper.updateWmsSalesOrder(wmsSalesOrder);
        }
        return orders.size();
    }

    /**
     * 批量删除销售订单
     *
     * @param ids 需要删除的销售订单主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteWmsSalesOrderByIds(Long[] ids)
    {
        if(ids == null || ids.length < 1){
            throw new ServiceException("缺少必要参数");
        }

        WmsSalesOrder wmsSalesOrder = new WmsSalesOrder();
        wmsSalesOrder.setIds(Arrays.asList(ids));
        List<WmsSalesOrder> orders = wmsSalesOrderMapper.selectWmsSalesOrderList(wmsSalesOrder);
        //校验销售订单状态
        List<String> nos = orders.stream()
                .filter(e -> OutOrderStatusEnum.CANCEL_PENDING_CONFIRMATION.getCode().equals(e.getOrderStatus())
                        || OutOrderStatusEnum.ACCOMPLISH.getCode().equals(e.getOrderStatus()))
                .map(WmsSalesOrder::getNo).collect(Collectors.toList());
        if(!nos.isEmpty()){
            throw new ServiceException("取消待确认或已完成状态的单据不能删除");
        }
        for (WmsSalesOrder order : orders) {
            if(OutOrderStatusEnum.PICKING.getCode().equals(order.getOrderStatus())){
                //校验进行中单据下的出入库单数据
                WmsOutStockOrder stockOrder = wmsOutStockOrderService.selectWmsOutStockOrderByRelOrderNo(order.getNo(), OutStockOrderTypeEnum.SALES.getCode());
                if(stockOrder != null && stockOrder.getTotalActualQty() > 0){
                    nos.add(order.getNo());
                }
            }
        }
        if(!nos.isEmpty()){
            throw new ServiceException(nos + "单据已有实际出库数量不能删除");
        }
        //删除明细数据
        List<String> orderNos = orders.stream().map(WmsSalesOrder::getNo).collect(Collectors.toList());
        wmsSalesOrderDetailService.deleteByOrderNos(orderNos);
        //出库单和出库单明细删除
        wmsOutStockOrderService.deleteWmsOutStockOrderByRelOrderNosAndType(orderNos, OutStockOrderTypeEnum.SALES.getCode());

        return wmsSalesOrderMapper.deleteWmsSalesOrderByIds(ids);
    }

    /**
     * 删除销售订单信息
     *
     * @param id 销售订单主键
     * @return 结果
     */
    @Override
    public int deleteWmsSalesOrderById(Long id)
    {
        return wmsSalesOrderMapper.deleteWmsSalesOrderById(id);
    }

    /**
     * 导出列表查询
     * @param entity    参数
     * @return 导出列表
     */
    @Override
    public List<WmsSalesOrderVo> exportList(WmsSalesOrder entity) {
        return wmsSalesOrderMapper.exportList(entity);
    }

    /**
     * 导入数据
     * @param list 导入数据列表
     * @return 错误列表
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<String> importExcel(List<WmsSalesOrderVo> list) {
        List<String> errList = new ArrayList<>();
        Map<String, List<WmsSalesOrderVo>> groupMap = list.stream().collect(Collectors.groupingBy(e -> e.getCustomerName() + ":" + DateUtil.formatDate(e.getPlanDeliveryTime())));
        Set<String> groupKeys = groupMap.keySet();
        for (String groupKey : groupKeys) {
            String[] split = groupKey.split(":");
            String customerName = split[0];
            String planDeliveryTime = split[1];
            List<WmsSalesOrderVo> wmsSalesOrderVos = groupMap.get(groupKey);
            WmsSalesOrder wmsSalesOrder = new WmsSalesOrder();
            wmsSalesOrder.setPlanDeliveryTime(DateUtil.parseDate(planDeliveryTime));
            wmsSalesOrder.setCustomerName(customerName);
            wmsSalesOrder.setTotalOrderQty(wmsSalesOrderVos.stream().mapToLong(e -> e.getOrderQty()).sum());
            if (wmsSalesOrder.getPlanDeliveryTime() == null) {
                errList.add("计划出库时间不能为空");
                continue;
            }
            if (wmsSalesOrder.getCustomerName() == null) {
                errList.add("客户名称不能为空");
                continue;
            }
            this.insertWmsSalesOrder(wmsSalesOrder);

            List<WmsSalesOrderDetail> details = new ArrayList<>();
            for (WmsSalesOrderVo wmsSalesOrderVo : wmsSalesOrderVos) {
                WmsSalesOrderDetail wmsSalesOrderDetail = new WmsSalesOrderDetail();
                wmsSalesOrderDetail.setOrderNo(wmsSalesOrder.getNo());
                wmsSalesOrderDetail.setOrderQty(wmsSalesOrderVo.getOrderQty());
                wmsSalesOrderDetail.setProductNo(wmsSalesOrderVo.getProductNo());
                WmsProduct wmsProduct = wmsProductService.selectWmsProductByProductNo(wmsSalesOrderVo.getProductNo());
                if (wmsProduct == null) {
                    errList.add("无效物料编码：" + wmsProduct.getProductNo());
                    continue;
                }
                wmsSalesOrderDetail.setProductName(wmsProduct.getProductName());
                wmsSalesOrderDetail.setProductUnit(wmsProduct.getCompany());
                details.add(wmsSalesOrderDetail);
            }
            if (CollUtil.isNotEmpty(details)) {
                wmsSalesOrderDetailService.batchInsertSalesOrderDetail(details);
            }
        }
        return errList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int confirm(List<Long> ids) {
        WmsSalesOrder order = new WmsSalesOrder();
        order.setIds(ids);
        List<WmsSalesOrder> orders = this.selectWmsSalesOrderList(order);
        orders = orders.stream().filter(e -> OutOrderStatusEnum.NEW.getCode().equals(e.getOrderStatus())).collect(Collectors.toList());
        if (orders.isEmpty()) {
            return 0;
        }
        String username = SecurityUtils.getUsername();
        Date date = DateUtils.getNowDate();
        for (WmsSalesOrder wmsSalesOrder : orders) {
            wmsSalesOrder.setUpdateBy(username);
            wmsSalesOrder.setUpdateTime(date);
            wmsSalesOrder.setOrderStatus(OutOrderStatusEnum.PICKING.getCode());
        }
        wmsSalesOrderMapper.batchUpdateSalesOrder(orders);

        //添加出库单
        for (WmsSalesOrder wmsSalesOrder : orders) {
            WmsSalesOrderDetail wmsSalesOrderDetail = new WmsSalesOrderDetail();
            wmsSalesOrderDetail.setOrderNo(wmsSalesOrder.getNo());
            List<WmsSalesOrderDetail> wmsSalesOrderDetails = this.wmsSalesOrderDetailService.selectWmsSalesOrderDetailList(wmsSalesOrderDetail);
            if (CollUtil.isEmpty(wmsSalesOrderDetails)) {
                throw new ServiceException("未维护明细数据");
            }
            List<StockDetailProductVo> stockDetailProductVos = new ArrayList<>();
            for (WmsSalesOrderDetail billDetail : wmsSalesOrderDetails) {
                StockDetailProductVo detailProductVo = new StockDetailProductVo();
                detailProductVo.setProductNo(billDetail.getProductNo());
                detailProductVo.setOrderQty(billDetail.getOrderQty());
                stockDetailProductVos.add(detailProductVo);
            }
            wmsOutStockOrderService.initBillStockOrder(wmsSalesOrder.getNo(), OutStockOrderTypeEnum.SALES.getCode(), stockDetailProductVos,wmsSalesOrder.getCustomerNo(),"");
        }
        return orders.size();
    }

    @Override
    @Transactional
    public int cancel(List<Long> ids) {
        WmsSalesOrder order = new WmsSalesOrder();
        order.setIds(ids);
        List<WmsSalesOrder> orders = this.selectWmsSalesOrderList(order);
        orders = orders.stream().filter(e -> OutOrderStatusEnum.NEW.getCode().equals(e.getOrderStatus())
                || OutOrderStatusEnum.PICKING.getCode().equals(e.getOrderStatus())).collect(Collectors.toList());
        if (orders.isEmpty()) {
            return 0;
        }
        for (WmsSalesOrder wmsSalesOrder : orders) {
            WmsOutStockOrder wmsOutStockOrder = wmsOutStockOrderService.selectWmsOutStockOrderByRelOrderNo(wmsSalesOrder.getNo(), OutStockOrderTypeEnum.SALES.getCode());
            if (wmsOutStockOrder!=null) {
                if (wmsOutStockOrder.getTotalActualQty() > 0){
                    throw new ServiceException("已出库不允许取消，单号：" + wmsOutStockOrder.getNo());
                }
                wmsOutStockOrder.setOrderStatus(OutOrderStatusEnum.CANCEL.getCode());
                this.wmsOutStockOrderService.updateWmsOutStockOrder(wmsOutStockOrder);
            }
            wmsSalesOrder.setOrderStatus(OutOrderStatusEnum.CANCEL.getCode());
        }
        wmsSalesOrderMapper.batchUpdateSalesOrder(orders);
        return orders.size();
    }

    /**
     * 确认取消
     * @param order 单据信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int confirmCancel(WmsSalesOrder order) {
        order = this.selectWmsSalesOrderById(order.getId());
        if(order == null){
            throw new ServiceException("单据不存在");
        }else if(!OutOrderStatusEnum.CANCEL_PENDING_CONFIRMATION.getCode().equals(order.getOrderStatus())){
            throw new ServiceException("该状态不是取消待确认，无法确认取消");
        }

        WmsOutStockOrder stockOrder = wmsOutStockOrderService.selectWmsOutStockOrderByRelOrderNo(order.getNo(), OutStockOrderTypeEnum.SALES.getCode());
        if(stockOrder != null){
            stockOrder.setOrderStatus(OutOrderStatusEnum.CANCEL.getCode());
            wmsOutStockOrderService.updateWmsOutStockOrder(stockOrder);
        }
        order.setOrderStatus(OutOrderStatusEnum.CANCEL.getCode());
        return this.updateWmsSalesOrder(order);
    }
}
